import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import { ToolkitStore } from '@reduxjs/toolkit/dist/configureStore';
import { AppStore, RecordList, StoreList, StoreRecordListBaseParams } from '../types';
import main from '../main';
import { clearEmptyKey, objectSortToString } from '../utils/utils';

// 请求成功时传送的参数
interface SuccessParams<T> extends StoreRecordListBaseParams<T> {
  list: Array<T>;
}

// 请求失败时传的参数
interface FailureParams extends StoreRecordListBaseParams<any> {
  error: string;
}

const listSlice = createSlice({
  name: 'list',
  initialState: {} as StoreList<any>,
  reducers: {
    listRequest: <T>(state: StoreList<T>, action: PayloadAction<StoreRecordListBaseParams<T>>) => {
      let key = createStoreListKey(action.payload);

      if (!state[key]) {
        state[key] = {
          fetching: false,
          loaded: false,
          model: action.payload.model,
          table: action.payload.table,
          path: action.payload.path ?? 'list',
          params: action.payload.params,
        };
      }
      state[key].fetching = true;
      return state;
    },

    listSuccess: <T>(state: StoreList<T>, action: PayloadAction<SuccessParams<T>>) => {
      let key = createStoreListKey(action.payload);
      let keyStart = createListKeyStart(action.payload);
      if (action.payload.forceRefresh) {
        let keys = Object.keys(state);
        for (let i of keys ?? []) {
          if (i.startsWith(keyStart)) {
            delete state[i];
          }
        }
      }
      if (!state[key]) {
        state[key] = {
          fetching: false,
          loaded: false,
          model: action.payload.model,
          table: action.payload.table,
          path: action.payload.path ?? 'list',
          params: action.payload.params,
        };
      }
      state[key].fetching = false;
      state[key].loaded = true;
      state[key].error = undefined;
      state[key].results = action.payload.list;
      return state;
    },

    listFailure: <T>(state: StoreList<T>, action: PayloadAction<FailureParams>) => {
      let key = createStoreListKey(action.payload);
      if (!state[key]) {
        state[key] = {
          fetching: false,
          loaded: false,
          model: action.payload.model,
          table: action.payload.table,
          path: action.payload.path ?? 'list',
          params: action.payload.params,
        };
      }
      state[key].fetching = false;
      state[key].loaded = true;
      state[key].error = action.payload.error;
      return state;
    },

    listClear: (state) => {
      return {};
    },
    listClearTable: (state: StoreList<any>, action: PayloadAction<StoreRecordListBaseParams<any>>) => {
      let keyStart = createListKeyStart(action.payload);
      let keys = Object.keys(state);
      for (let i of keys ?? []) {
        if (i.startsWith(keyStart)) {
          delete state[i];
        }
      }
      return state;
    },
  },
});

export const { listRequest, listSuccess, listFailure, listClear, listClearTable } = listSlice.actions;
export default listSlice.reducer;

export const listEffect = {
  'list/clear': (store: ToolkitStore<AppStore>) => store.dispatch(listClear()),
  'list/listRequest': async <T>(store: ToolkitStore<AppStore>, action: PayloadAction<StoreRecordListBaseParams<T>>) => {
    let key = createStoreListKey(action.payload);

    let list: RecordList<T> = store.getState().list?.[key];
    if (list?.loaded && list?.results && !list.error && !action.payload.forceRefresh) {
      store.dispatch(listSuccess({ ...action.payload, list: list.results }));
      if (action.payload.callback) {
        action.payload.callback!(200, '获取成功');
      }
    } else {
      let code: number | undefined;
      let msg: string | undefined;
      let headers: any;
      let url = `${action.payload.model}/${action.payload.table}/${action.payload.path ?? 'list'}`;
      if (url.includes('/gen/')) {
        headers = { datasource: 'master' };
      }
      try {
        // 请求接口 处理数据 并发送成功或失败action
        let res = await main.api.get(url, { params: action.payload.params, headers });
        let data = res.data;
        code = data.code;
        if (data.code === 200) {
          msg = data.msg ?? '获取成功';
          store.dispatch(
            listSuccess({
              model: action.payload.model,
              table: action.payload.table,
              path: action.payload.path ?? 'list',
              params: action.payload.params,
              list: data.data,
              forceRefresh: action.payload.forceRefresh,
            })
          );
        } else {
          msg = data.msg || '获取失败';
          store.dispatch(
            listFailure({
              model: action.payload.model,
              table: action.payload.table,
              path: action.payload.path ?? 'list',
              params: action.payload.params,
              error: msg!,
            })
          );
        }
      } catch (e: any) {
        code = 500;
        msg = e.message ?? '获取失败';
        store.dispatch(
          listFailure({
            model: action.payload.model,
            table: action.payload.table,
            path: action.payload.path ?? 'list',
            params: action.payload.params,
            error: msg!,
          })
        );
      } finally {
        if (action.payload.callback) {
          action.payload.callback!(code, msg);
        }
      }
    }
  },
};

function createListKeyStart(payload: StoreRecordListBaseParams<any>) {
  let { model, table, path } = payload;
  let key = model + '/' + table + '/' + (path ?? 'list');
  return key;
}

export function createStoreListKey(payload: StoreRecordListBaseParams<any>) {
  let { params, model, table, path } = payload;
  let key = objectSortToString(clearEmptyKey(params ?? {}));
  key = model + '/' + table + '/' + (path ?? 'list') + ':' + key;
  return key;
}
